#include "QMyMdiArea.h"

QMyMdiArea::QMyMdiArea()
{	
  setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
	
	mousePressed=false;
	p1x=p1y=p2x=p2y=0;	
	
}

void QMyMdiArea::paintEvent(QPaintEvent * paintEvent)
{
  QPainter painter(viewport());
  
  //dessine un fond gris
  painter.setBrush(QColor(100,100,128));
  painter.drawRect(this->rect());
  
  //dessine une boite avec des ronds symbolisant les entrées sorties
         
  painter.setPen(QColor(0,0,0));
  
  for(int i=0;i<subWindowList().size();i++)
  {
    painter.setBrush(QColor(128,128,200,200));

    
    painter.drawRoundedRect(subWindowList()[i]->x()-s,
                     subWindowList()[i]->y()-s,
                     subWindowList()[i]->width()+2*s,
                     subWindowList()[i]->height()+2*s,5,5);
        
    int cx=subWindowList()[i]->x()+subWindowList()[i]->width()+s/2.0;
    int cy=subWindowList()[i]->y()+subWindowList()[i]->height()/2.0-s/2.0;
    if(((p1x-cx-s/2.0)*(p1x-cx-s/2.0)+(p1y-cy-s/2.0)*(p1y-cy-s/2.0))<(s*s/4))
    {painter.setBrush(QColor(128,200,128));}
    else{painter.setBrush(QColor(200,200,200,200));}
    painter.drawEllipse(cx,cy, s,s);
    
    int nbInputs=((QCVModuleHandler*)subWindowList()[i])->getNbInputs();                    
    for(int k=0;k<nbInputs;k++)
    {
      cx=subWindowList()[i]->x()-s/2.0-s;
      cy=subWindowList()[i]->y()+subWindowList()[i]->height()/2.0-s/2.0+(k-nbInputs/2)*(s+1);
      if(((p2x-cx-s/2.0)*(p2x-cx-s/2.0)+(p2y-cy-s/2.0)*(p2y-cy-s/2.0))<(s*s/4))
      {painter.setBrush(QColor(128,200,128));}
      else{painter.setBrush(QColor(200,200,200,200));}
      painter.drawEllipse (cx,cy,s,s);
    }
  }
  
  //dessine une fleche blanche
  if(mousePressed)
  {
    painter.setPen(QColor(255,255,255));
    painter.drawLine(p1x,p1y,(p2x-p1x)/2+p1x,p1y);
    painter.drawLine((p2x-p1x)/2+p1x,p1y,(p2x-p1x)/2+p1x,p2y);
    painter.drawLine((p2x-p1x)/2+p1x,p2y,p2x,p2y); 
    painter.drawLine(p2x-s*(2*(p1x<p2x)-1),p2y+s,p2x,p2y);
    painter.drawLine(p2x-s*(2*(p1x<p2x)-1),p2y-s,p2x,p2y);
  }
  
  //dessine la liste des connections en vert ou rouge si non valide ou blanc si selectionnée
  for(int i=0;i<links.size();i++)
  {
      int P1X=links[i].mod1->x()+links[i].mod1->width()+s;
      int P1Y=links[i].mod1->y()+links[i].mod1->height()/2.0;
      
      int P2X=links[i].mod2->x()-s;
      int P2Y=links[i].mod2->y()+links[i].mod2->height()/2.0+(links[i].idInput-links[i].mod2->getNbInputs()/2)*(s+1);
      
			if(links[i].selected==false)
			{	
				if(isLinkValid(&links[i])){painter.setPen(QColor(0,255,0));}
				else{painter.setPen(QColor(255,0,0));}
			}
			else {painter.setPen(QColor(255,255,255));}
			

      painter.drawLine(P1X,P1Y,(P2X-P1X)/2+P1X,P1Y);
      painter.drawLine((P2X-P1X)/2+P1X,P1Y,(P2X-P1X)/2+P1X,P2Y);
      painter.drawLine((P2X-P1X)/2+P1X,P2Y,P2X,P2Y); 
      painter.drawLine(P2X-s*(2*(P1X<P2X)-1),P2Y+s,P2X,P2Y);
      painter.drawLine(P2X-s*(2*(P1X<P2X)-1),P2Y-s,P2X,P2Y);
  }
}

void QMyMdiArea::mouseMoveEvent ( QMouseEvent * e )
{
  mousePressed=true;
  
  p2x=e->x();
  p2y=e->y();
  viewport()->update();
  
}

void QMyMdiArea::mousePressEvent ( QMouseEvent * e )
{
  p1x=e->x();
  p1y=e->y();
  p2x=e->x();
  p2y=e->y();
  
  //selection/deselection des liens
  for(int i=0;i<links.size();i++)
  {
    int p=5;
    int P1X=links[i].mod1->x()+links[i].mod1->width()+s;
    int P1Y=links[i].mod1->y()+links[i].mod1->height()/2.0;
    int P2X=links[i].mod2->x()-s;
    int P2Y=links[i].mod2->y()+links[i].mod2->height()/2.0+(links[i].idInput-links[i].mod2->getNbInputs()/2)*(s+1);
  
    if((((p1x>(P1X-p) && p1x<((P2X-P1X)/2+P1X+p))||(p1x>((P2X-P1X)/2+P1X-p) && p1x<(P1X+p))) && ((p1y<(P1Y+p) && p1y>(P1Y-p))||(p1y<(P1Y+p) && p1y>(P1Y-p)))) ||
       (((p1x>((P2X-P1X)/2+P1X-p) && p1x<(P2X+p))||(p1x>(P2X-p) && p1x<((P2X-P1X)/2+P1X+p))) && ((p1y<(P2Y+p) && p1y>(P2Y-p))||(p1y<(P2Y+p) && p1y>(P2Y-p)))) || 
       ((p1x>((P2X-P1X)/2+P1X-p) && p1x<((P2X-P1X)/2+P1X+p)) && ((p1y<(P2Y+p) && p1y>(P1Y-p))||(p1y<(P1Y+p) && p1y>(P2Y-p))))
      )
    {
			links[i].selected=true;
    }
    else
    {
			links[i].selected=false;
    }
  }
  
  if(e->button()==Qt::RightButton)
  {
    //affichage des informations sur les E/S des modules
    for(int i=0;i<subWindowList().size();i++)
    {
      //Calcul des coord de l'entrée k du module i
      for(int k=0;k<((QCVModuleHandler*)subWindowList()[i])->getNbInputs();k++)
      {
        int inputX=subWindowList()[i]->x()-s;
        int inputY=subWindowList()[i]->y()+subWindowList()[i]->height()/2.0+(k-((QCVModuleHandler*)subWindowList()[i])->getNbInputs()/2)*(s+1);   
        if (sqrt((inputX-p1x)*(inputX-p1x)+(inputY-p1y)*(inputY-p1y))<s/2)
        {
          QMessageBox::information(NULL,"ok",((QCVModuleHandler*)subWindowList()[i])->help(k));
        }
			}
			int outputX=subWindowList()[i]->x()+subWindowList()[i]->width()+s;
  		int outputY=subWindowList()[i]->y()+subWindowList()[i]->height()/2.0;
			if (sqrt((outputX-p1x)*(outputX-p1x)+(outputY-p1y)*(outputY-p1y))<s/2)
      {
        QMessageBox::information(NULL,"ok",((QCVModuleHandler*)subWindowList()[i])->help(-1));
      }
    }
  }
	viewport()->update();
}

void QMyMdiArea::mouseReleaseEvent ( QMouseEvent * e )
{
  mousePressed=false;
  
  //on crée un lien 
  Link * new_link=new Link;
  new_link->mod1=NULL;
  new_link->mod2=NULL;
  new_link->selected=false;
  new_link->idInput=0;
  
  //on cherche le module dont la sortie est la plus proche du debut de la fleche
  //on cherche le module dont une de ses entrées est la plus proche de la fin de la fleche
  int outputDmin=100000000;
  int inputDmin=100000000;
  for(int i=0;i<subWindowList().size();i++)
  {
    //coord de la sortie du module
    int outputX=subWindowList()[i]->x()+subWindowList()[i]->width()+s;
    int outputY=subWindowList()[i]->y()+subWindowList()[i]->height()/2.0;
    
    //calcul de la distance entre la sortie et le debut de la fleche
    int outputD=(outputX-p1x)*(outputX-p1x)+(outputY-p1y)*(outputY-p1y);
    if(outputD<outputDmin)
    {
      outputDmin=outputD;  
      new_link->mod1=((QCVModuleHandler*)subWindowList()[i]);
    }
    
    for(int k=0;k<((QCVModuleHandler*)subWindowList()[i])->getNbInputs();k++)
    {
      //Calcul des coord de l'entrée k du module i
      int inputX=subWindowList()[i]->x()-s-s;
      int inputY=subWindowList()[i]->y()+subWindowList()[i]->height()/2.0+(k-((QCVModuleHandler*)subWindowList()[i])->getNbInputs()/2)*(s+1);
      
      //Calcul de la distance par rapport a la fin de la fleche
      int inputD=(inputX-p2x)*(inputX-p2x)+(inputY-p2y)*(inputY-p2y);
      if(inputD<inputDmin)
      {
        inputDmin=inputD;
        new_link->mod2=((QCVModuleHandler*)subWindowList()[i]);
        new_link->idInput=k;
      }
    } 
  }
  
  //on ajoute le lien dans la liste 
  if((new_link->mod1!=NULL) && (new_link->mod2!=NULL) && (new_link->mod1!=new_link->mod2) && sqrt((p1x-p2x)*(p1x-p2x)+(p1y-p2y)*(p1y-p2y))>50)
  {
    apply_link(new_link);
    links+=*new_link;
  }
	viewport()->update();
}

void QMyMdiArea::create_link(QCVModuleHandler * mod1,QCVModuleHandler * mod2,int idInput)
{
  Link * new_link=new Link;
  new_link->mod1=mod1;
  new_link->mod2=mod2;
  new_link->selected=false;
  new_link->idInput=idInput;
  if((new_link->mod1!=NULL) && (new_link->mod2!=NULL))
  {
    apply_link(new_link);
    links+=*new_link;
  }
	viewport()->update();
}

void QMyMdiArea::create_link(int id_mod1,int id_mod2,int idInput)
{
  Link * new_link=new Link;
  new_link->mod1=((QCVModuleHandler*)subWindowList()[id_mod1]);
  new_link->mod2=((QCVModuleHandler*)subWindowList()[id_mod2]);
  new_link->selected=false;
  new_link->idInput=idInput;
  if((new_link->mod1!=NULL) && (new_link->mod2!=NULL))
  {
    apply_link(new_link);
    links+=*new_link;
  }  
	viewport()->update();
}

void QMyMdiArea::apply_link(Link * l)
{
  if(l->idInput==0)
  {
    connect(l->mod1,SIGNAL(output(cv::Mat&)),l->mod2,SLOT(input0(cv::Mat&)));
  }
  else if(l->idInput==1)
  {
    connect(l->mod1,SIGNAL(output(cv::Mat&)),l->mod2,SLOT(input1(cv::Mat&)));
  }
  else if(l->idInput==2)
  {
    connect(l->mod1,SIGNAL(output(cv::Mat&)),l->mod2,SLOT(input2(cv::Mat&)));
  }
  else if(l->idInput==3)
  {
    connect(l->mod1,SIGNAL(output(cv::Mat&)),l->mod2,SLOT(input3(cv::Mat&)));
  }
}

void QMyMdiArea::remove_link(Link * l)
{
  if(l->idInput==0)
  {
    disconnect(l->mod1,SIGNAL(output(cv::Mat&)),l->mod2,SLOT(input0(cv::Mat&)));
  }
  else if(l->idInput==1)
  {
    disconnect(l->mod1,SIGNAL(output(cv::Mat&)),l->mod2,SLOT(input1(cv::Mat&)));
  }
  else if(l->idInput==2)
  {
    disconnect(l->mod1,SIGNAL(output(cv::Mat&)),l->mod2,SLOT(input2(cv::Mat&)));
  }
  else if(l->idInput==3)
  {
    disconnect(l->mod1,SIGNAL(output(cv::Mat&)),l->mod2,SLOT(input3(cv::Mat&)));
  }
}

bool QMyMdiArea::isLinkValid(Link * l)
{
	if( (l->mod2->help(l->idInput).contains(l->mod1->help(-1))) || (l->mod2->help(-1).contains(l->mod1->help(l->idInput))) )
	{
		return true;
	}
	else
	{
		return false;
	}
}

void QMyMdiArea::remove_selected_links()
{
  for(int i=0;i<links.size();i++)
  {  
    if((links[i].selected==true))
    {
			remove_link(&links[i]);    
			links.removeAt(i);
      i--;
    }
  }
	viewport()->update();
}

void QMyMdiArea::remove_links(QCVModuleHandler*handler)
{
  for(int i=0;i<links.size();i++)
  {  
    if((links[i].mod1==handler) || (links[i].mod2==handler))
    {
			remove_link(&links[i]);    
			links.removeAt(i);
      i--;
    }
  }
	viewport()->update();
}

QList<Link> QMyMdiArea::getLinks()
{
  return links;
}

int QMyMdiArea::getId(QCVModuleHandler*p)
{
  for(int i=0;i<subWindowList().size();i++)
  {
    if((QCVModuleHandler*)subWindowList()[i]==p)
    {
      return i;
    }  
  }
  return -1;
}


